package view.GUI.otherView;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.controlsfx.dialog.Dialogs;
import org.controlsfx.validation.ValidationSupport;

import view.Validator.DoubleNumberRangeValidator;
import view.Validator.IntegerNumberRangeValidator;
import view.Validator.MyValidationSupport;
import model.Configuration;
import model.handler.fileHandling.FileHandler;
import controller.Controller;
import enums.GUIText;
import enums.Message;
import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.Separator;
import javafx.scene.control.TextField;
import javafx.scene.input.KeyCode;
import javafx.scene.input.KeyEvent;
import javafx.scene.layout.GridPane;
import javafx.stage.Modality;
import javafx.stage.Stage;
import javafx.stage.Window;

/**
 * Provides the Logout-View if the user wants to log out off the session.
 * 
 * @version %I%, %G%
 */
public final class Logout extends Application {
	
	private static Logger log = LogManager.getLogger("ERROR");
	private static Logger infoLog = LogManager.getLogger("INFO");
	private static Logger userLog = LogManager.getLogger("USER");
	/**
	 * LayoutManager using a GridPane
	 */
	private GridPane grid;
	
	private Label lblTitle;
	private Separator sepTop;
	private Separator sepBottom;

	private TextField txtCoins;
	private Label lblCoins;

	private TextField txtCash;
	private Label lblCash;

	private Button btnLogout;

	private Scene scene;
	private Stage primaryStage;

	private Controller controller;

	private Window owner;

	private ValidationSupport valSup;
	
	private int rowCounter;


	/**
	 * Only constructor.
	 */
	public Logout(Window owner) {
		this.rowCounter = 1;
		valSup = MyValidationSupport.createDefaultValidationSupport();
		createWidgets();
		setupValidation();
		setLayout();
		addWidgets();
		setupInteraction();
		this.owner = owner;
		start(new Stage());

		this.controller = Controller.getInstance();
		controller.setLogout(this);
	}

	/**
	 * Displays a popup for user information with a specified message.
	 * 
	 * @param msg
	 *            Message to be displayed in the Popup
	 */
	public void logoutFailed(Message msg) {
		Dialogs.create()
				.message(msg.toString())
				.owner(primaryStage)
				.showError();
		infoLog.info("Logout failed: " + msg.toString());
	}

	/**
	 * Closes the Logout window because the logout attempt was successful.
	 */
	public void logoutSuccess() {
		userLog.info("User logged out successfully");
		FileHandler.saveDatabase();
		primaryStage.close();
	}

	// HELPER METHODS BELOW

	/**
	 * Forwards a Logout attempt to the model where the validity check of the
	 * Logout attempt is performed.
	 * <p>
	 * Displays popups for user information if the Logout failed.
	 */
	private void tryLogout() {
		try {
			controller.tryLogout(txtCash.getText().trim(), txtCoins.getText()
					.trim());
		} catch (NumberFormatException nfEx) {
			log.error("Logout failed: " + nfEx.toString());
			Dialogs.create()
					.owner(primaryStage)
					.showException(nfEx);
		} catch (IllegalArgumentException ex) {
			Dialogs.create()
			.owner(primaryStage)
			.showException(ex);
			log.error("Logout failed: " + ex.toString());
		}
	}

	/**
	 * This helper-method sets the layout for the whole view.
	 */
	private void setLayout() {
		btnLogout.setDisable(true);
		btnLogout.setId("logout");
		lblTitle.setId("topic");
		GridPane.setColumnSpan(sepBottom, 4);
		GridPane.setColumnSpan(sepTop, 4);
	}

	/**
	 * This helper-method adds all Eventhandler provided and needed by this view
	 */
	private void setupInteraction() {

		txtCoins.setOnKeyReleased(new EventHandler<KeyEvent>() {

			@Override
			public void handle(KeyEvent e) {
				btnLogout.setDisable(MyValidationSupport.isNodeToDisable(valSup));
				if (e.getCode() == KeyCode.ENTER && !MyValidationSupport.isNodeToDisable(valSup)) {
					tryLogout();
				}
			}
		});

		txtCash.setOnKeyReleased(new EventHandler<KeyEvent>() {

			@Override
			public void handle(KeyEvent e) {
				btnLogout.setDisable(MyValidationSupport.isNodeToDisable(valSup));
			}
		});

		// Beim Klicken des Buttons Logout wird die Methode tryLogout()
		// aufgerufen
		btnLogout.setOnAction(new EventHandler<ActionEvent>() {

			@Override
			public void handle(ActionEvent event) {
				tryLogout();
			}
		});
	}

	/**
	 * Sets up the validation for the textfields.
	 */
	private void setupValidation() {
		valSup.registerValidator(txtCash, true,
				DoubleNumberRangeValidator.createMinNumberRangeValidator(0));
		valSup.registerValidator(txtCoins, true,
				IntegerNumberRangeValidator.createMinNumberRangeValidator(0));
	}

	/**
	 * This helper-method creates all widgets that are provided by this view
	 */
	private void createWidgets() {
		
		lblTitle = new Label(GUIText.LOGOUT.toString());
		sepBottom = new Separator();
		sepTop = new Separator();
		grid = new GridPane();

		txtCash = new TextField();
		txtCoins = new TextField();

		lblCash = new Label(GUIText.ACTUALCASH.toString());
		lblCoins = new Label(GUIText.COUNT.toString() + " " + GUIText.TOKEN.toString() + "n");

		btnLogout = new Button(GUIText.LOGOUT.toString());
	}

	/**
	 * This helper-method adds all created widgets to the scene.
	 */
	private void addWidgets() {

		grid.add(lblTitle, 0, rowCounter++);
		grid.add(sepTop, 0, rowCounter++);
		
		grid.add(lblCash, 0, rowCounter);
		grid.add(txtCash, 1, rowCounter++);

		grid.add(lblCoins, 0, rowCounter);
		grid.add(txtCoins, 1, rowCounter++);

		grid.add(btnLogout, 1, rowCounter++);
		
		grid.add(sepBottom, 0, rowCounter++);
	}
	
	@Override
	public void start(Stage primaryStage) {

		scene = new Scene(grid);
		grid.getStyleClass().add("grid");
		scene.getStylesheets().add(getClass().getResource(Configuration.STYLELOGIN).toExternalForm());
		scene.getStylesheets().add(getClass().getResource(Configuration.STYLEVALIDATION).toExternalForm());
		scene.getStylesheets().add(getClass().getResource(Configuration.STYLEROOT).toExternalForm());
		this.primaryStage = primaryStage;
		this.primaryStage.initModality(Modality.WINDOW_MODAL);
		this.primaryStage.initOwner(owner);
		primaryStage.setScene(scene);
		primaryStage.setTitle(GUIText.LOGOUT.toString());
		primaryStage.setResizable(true);
		primaryStage.centerOnScreen();
		primaryStage.show();
	}
}
